package com.fangsheng.redis.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.UUID;

/**
 * @创建人: 放生
 * @创建时间: 2021/8/7
 * @描述:
 */
@Component
public class JedisUtils {

    private static final int setnxSuccss = 1;

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    JedisPool getJedisPoolInstance;

    private int indexdb=0;

    public Long hSet(String key, String value, String fiid) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            return jedis.hset(key, fiid, value);
        } catch (Exception e) {
            log.error("hset异常", e);
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public String hGet(String key, String fiid) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            return jedis.hget(key, fiid);
        } catch (Exception e) {
            log.error("hget异常", e);
            return null;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public Boolean exists(String key) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            return jedis.exists(key);
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * redis 库存操作
     */
    public Integer executeLua(List<String> key, List<String> value, String lua) {
        Jedis jedis = null;
        jedis = getJedisPoolInstance.getResource();
        jedis.select(indexdb);
        try {
            String s = String.valueOf(jedis.eval(lua, key, value));
            return Integer.parseInt(s);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * <p>
     * 通过key获取储存在redis中的value
     * @return 成功返回value 失败返回null
     */
    public String get(String key) {
        Jedis jedis = null;
        String value = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            value = jedis.get(key);
        } catch (Exception e) {
            log.error("redis查询异常", e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return value;
    }

    /**
     * <p>
     * 通过key获取储存在redis中的value
     * @return 成功返回value 失败返回null
     */
    public byte[] get(byte[] key) {
        Jedis jedis = null;
        byte[] value = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            value = jedis.get(key);
        } catch (Exception e) {
            log.error("redis查询异常", e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return value;
    }

    /**
     * <p>
     * 向redis存入key和value,并释放连接资源
     * @return 成功 返回OK 失败返回 0
     */
    public String set(String key, Object value) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            return jedis.set(key, (String) value);
        } catch (Exception e) {
            log.error(e.getMessage());
            return "0";
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * <p>
     * 删除指定的key,也可以传入一个包含key的数组
     * @return 返回删除成功的个数
     */
    public Long del(String... keys) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            Long v = jedis.del(keys);
            return v;
        } catch (Exception e) {
            log.error(e.getMessage());
            return 0L;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * <p>
     * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除。
     * @return 成功返回1 如果存在 和 发生异常 返回 0
     */
    public Long expire(String key, int value) {
        Jedis jedis = null;
        try {
            jedis = getJedisPoolInstance.getResource();
            jedis.select(indexdb);
            Long v = jedis.expire(key, value);
            return v;
        } catch (Exception e) {
            log.error(e.getMessage());
            return 0L;
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    /**
     * 获取锁
     *
     * @param lockKey        定义锁的key
     * @param notLockTimeOut 没有获取锁的超时时间
     * @param lockTimeOut    使用锁的超时时间
     * @return
     */
    public String getLock(String lockKey, int notLockTimeOut, int lockTimeOut) {
        // 获取Redis连接
        Jedis jedis = getJedisPoolInstance.getResource();
        try {
            // 定义没有获取锁的超时时间
            Long endTimeOut = System.currentTimeMillis() + notLockTimeOut;
            while (System.currentTimeMillis() < endTimeOut) {
                String lockValue = UUID.randomUUID().toString();
                jedis.select(indexdb);

                // 获取锁
                if (jedis.setnx(lockKey, lockValue) == setnxSuccss) {
                    jedis.expire(lockKey, lockTimeOut / 1000);
                    return lockValue;
                }
            }
        } catch (Exception e) {
            log.info("加锁异常", e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * 释放锁 其实就是将该key删除
     *
     * @return
     */
    public Boolean unLock(String lockKey, String lockValue) {
        Jedis jedis = getJedisPoolInstance.getResource();
        jedis.select(indexdb);
        try {
            // 删除对应的锁
            if (lockValue.equals(jedis.get(lockKey))) {
                return jedis.del(lockKey) > 0 ? true : false;
            }
        } catch (Exception e) {
            log.info("释放锁异常", e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return false;
    }

    /**
     * 序列化
     *
     * @param object
     * @return
     */
    public static byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
            return bytes;
        } catch (Exception e) {

        }
        return null;
    }

    /**
     * 反序列化
     *
     * @param bytes
     * @return
     */
    public static <Do> Do unserialize(byte[] bytes, Class<Do> doClass) {
        ByteArrayInputStream bais = null;
        try {
            bais = new ByteArrayInputStream(bytes);
            ObjectInputStream ois = new ObjectInputStream(bais);
            Do targetDo = doClass.newInstance();
            BeanUtils.copyProperties(ois.readObject(), targetDo);
            return targetDo;
        } catch (Exception e) {

        }
        return null;
    }


}
